package edu.hawaii.duedates.libraries;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.HttpUnitOptions;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebForm;
import com.meterware.httpunit.WebLink;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
import com.meterware.httpunit.WebTable;
import edu.hawaii.duedates.datastore.ResultsList;

/**
 * A class for retrieving information the Hawaii State Public Library System website.
 * 
 * @author Arthur Shum and Erin Kim.
 */
public class HawaiiStateLibrary extends Library {

  /** Support serialization. */
  private static final long serialVersionUID = 1L;
  
  /** The URL to log in to the Hawaii State Public Library System. */
  private static final String URL = "http://www.librarieshawaii.org/index_text.htm";

  private static final String NAME = "Hawaii State Library";

  /**
   * Returns the library's name.
   * 
   * @return The library's name.
   */
  public String getName() {
    return NAME;
  }

  /**
   * Default constructor.
   */
  public HawaiiStateLibrary() {
    super();
  }
  
  /**
   * Convenience constructor to create a HawaiiStateLibrary object, given a patron's library barcode
   * number and their PIN (usually the last 4 digits of their phone number).
   * 
   * @param barcode The patron's library card barcode number.
   * @param pin The patron's PIN.
   */
  public HawaiiStateLibrary(String barcode, String pin) {
    this.username = barcode;
    this.password = pin;
  }
    
  /**
   * Attempts to log in to the Hawaii State Public Library System.
   * 
   * @return The WebConversation after logging in.
   * @throws Exception If an errors occurs while logging in.
   */
  private WebConversation login() throws Exception {
    try {
      // Website has bogus JavaScript code.
      HttpUnitOptions.setExceptionsThrownOnScriptError(false);
      // create the conversation object which will maintain state for us
      WebConversation conversation = new WebConversation();
      WebRequest request = new GetMethodWebRequest(URL);
      WebResponse response = conversation.getResponse(request);
      WebLink link = response.getLinkWith("Log In");
      link.click();
      response = conversation.getCurrentPage();
      WebForm form = response.getForms()[0];
      form.setParameter("sec1", this.username);
      form.setParameter("sec2", this.password);
      form.submit();
      response = conversation.getCurrentPage();
      if (response.getText().contains("Login failed")) {
        throw new Exception();
      }
      return conversation;
    }
    catch (Exception e) {
      throw new Exception(NAME + ": Error while logging in.", e);
    }
  }

  /**
   * Retrieves information about items checked out from the Hawaii State Library by the logged-in
   * patron. The information is stored in a table where the text of cell 0,0 is "Title".
   * 
   * @return A ResultsList that holds information about checked-out items.
   * @throws Exception If an error occurs while retrieving info.
   */
  @Override
  public ResultsList getInfo() throws Exception {
    try {
      WebConversation conversation = this.login();
      WebResponse response = conversation.getCurrentPage();
      WebLink link = response.getLinkWith("Items Out");
      link.click();
      response = conversation.getCurrentPage();
      WebTable table = response.getTableStartingWith("Title");
      // If the table containing the information doesn't exist, return empty ArrayList.
      if (table == null) {
        return new ResultsList();
      }
      else {
        return parseResults(table);
      }
    }
    catch (Exception e) {
      // if the exception originates from this method
      if (e.getMessage() == null) {
        throw new Exception(NAME + ": Error while retrieving information.", e );
      }
      else {
        throw new Exception(e.getMessage(), e);
      }
    }
  }

  /**
   * Parses the table containing information about checked-out items, and stores the information for
   * each item into a BorrowedItem. In the table, each row is for a separate item; column 0 is for
   * the title and author; column 1 is for the checkout date; and column 2 is for the due date.
   * 
   * @param table The WebTable containing checked-out item information.
   * @return A ResultsList that holds information about checked-out items.
   */
  private ResultsList parseResults(WebTable table) {

    ResultsList results = new ResultsList();

    // String items = "\nResults for the Hawaii State Public Library System:\n\n";
    for (int i = 1; i < table.getRowCount(); i++) {
      String titleAuthor = table.getCellAsText(i, 0);
      // Find where the title ends and where the author begins.
      int titleEnd = titleAuthor.indexOf(" /\n");
      int authorBegin = titleAuthor.indexOf("by ", titleEnd) + 3;
      // Skip first 2 characters: "| "
      String title = titleAuthor.substring(2, titleEnd);
      String author = titleAuthor.substring(authorBegin);
      String outDate = table.getCellAsText(i, 1);
      String dueDate = table.getCellAsText(i, 2);

      // format due date into YYYYMMDD form
      String mm = dueDate.substring(0, 2);
      String dd = dueDate.substring(3, 5);
      String yyyy = dueDate.substring(6, 10);
      String yyyymmddDueDate = "".concat(yyyy + mm + dd);

      // format item information for printing
      String formattedResults = "";
      formattedResults = formattedResults.concat("Hawaii State Public Library System\n");
      formattedResults = formattedResults.concat("Title   :  " + title + "\n");
      formattedResults = formattedResults.concat("Author  :  " + author + "\n");
      formattedResults = formattedResults.concat("Out Date:  " + outDate + "\n");
      formattedResults = formattedResults.concat("Due Date:  " + dueDate + "\n\n");

      results.add("HawaiiStateLibrary", title, yyyymmddDueDate, formattedResults);
    }
    return results;
  }
  
}
